package net.thermetics.fx.services.impl;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.namespace.QName;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.dom.DOMSource;
import javax.xml.xquery.XQConnection;
import javax.xml.xquery.XQException;
import javax.xml.xquery.XQExpression;
import javax.xml.xquery.XQSequence;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.htmlcleaner.DomSerializer;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import org.htmlcleaner.XPatherException;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import net.sf.saxon.xqj.SaxonXQDataSource;
import net.thermetics.fx.model.Forum;
import net.thermetics.fx.model.ForumThread;
import net.thermetics.fx.model.ForumTopic;
import net.thermetics.fx.services.ForumService;
import net.thermetics.fx.util.GAEConnectionManager;

public class ForumServiceImpl implements ForumService {
	private static final String USER_AGENT = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7";
	
	@Override
	public List<ForumTopic> getTopics(String forumID) throws IllegalStateException, IOException, XQException, ParserConfigurationException {
		DefaultHttpClient client = new DefaultHttpClient(new GAEConnectionManager(), new BasicHttpParams());
		HttpGet get = new HttpGet("http://www.christianforums.com/" + forumID);
		get.addHeader("User-Agent", USER_AGENT);
		HttpResponse resp = client.execute(get);
		
		HttpEntity ent = resp.getEntity();
		System.out.println("   response: " + resp.getStatusLine());
		
		HtmlCleaner cleaner = new HtmlCleaner();
		TagNode root = cleaner.clean(ent.getContent());
		Node parsedNode = parseTopics(new DomSerializer(cleaner.getProperties(), true).createDOM(root));

		return extractTopics(parsedNode);
	}
	
	private Node parseTopics(Node node) throws XQException, FileNotFoundException {
		SaxonXQDataSource xqs = new SaxonXQDataSource();
		XQConnection conn = xqs.getConnection();
		XQExpression expr = conn.createExpression();
		
		expr.bindDocument(new QName("doc"), new DOMSource(node), null);
		
		InputStream query = new FileInputStream("WEB-INF/xquery/forum.xq");

		XQSequence results = expr.executeQuery(query);
		
		if (results.next()) {
			return results.getNode();
		}
		else {
			return null;
		}
	}
	
	private List<ForumTopic> extractTopics(Node xmlRoot) {
		List<ForumTopic> topics = new ArrayList<ForumTopic>();
		
		//each child is a <thread>
		NodeList children = xmlRoot.getChildNodes();
		for (int c = 0; c < children.getLength(); c++) {
			Node child = children.item(c);
			topics.add(extractTopic(child));
		}
		return topics;
	}
	
	private ForumTopic extractTopic(Node threadNode) {
		ForumTopic topic = new ForumTopic();
		
		if (threadNode instanceof Element) {
			Element e = (Element)threadNode;
			topic.setLink(e.getAttribute("id"));
			topic.setTitle(e.getTextContent());
		}
		else {
			topic.setTitle("No Title");
			topic.setLink("#");
		}
		
		return topic;
	}

	@Override
	public List<Forum> getForums() throws ClientProtocolException, IOException, XQException, ParserConfigurationException {
		DefaultHttpClient client = new DefaultHttpClient(new GAEConnectionManager(), new BasicHttpParams());
		HttpGet get = new HttpGet("http://www.christianforums.com/");
		get.addHeader("User-Agent", USER_AGENT);
		HttpResponse resp = client.execute(get);
		
		HttpEntity ent = resp.getEntity();
		System.out.println("   response: " + resp.getStatusLine());
		
		HtmlCleaner cleaner = new HtmlCleaner();
		TagNode root = cleaner.clean(ent.getContent());
		Node parsedNode = parseForums(new DomSerializer(cleaner.getProperties(), true).createDOM(root));

		return extractForums(parsedNode);
	}
	
	private Node parseForums(Node node) throws XQException, FileNotFoundException {
		SaxonXQDataSource xqs = new SaxonXQDataSource();
		XQConnection conn = xqs.getConnection();
		XQExpression expr = conn.createExpression();
		
		expr.bindDocument(new QName("doc"), new DOMSource(node), null);
		
		InputStream query = new FileInputStream("WEB-INF/xquery/forumlist.xq");

		XQSequence results = expr.executeQuery(query);
		
		if (results.next()) {
			return results.getNode();
		}
		else {
			return null;
		}
	}
	
	private List<Forum> extractForums(Node forumListNode) {
		List<Forum> forums = new ArrayList<Forum>();
		
		//each child is a <forum>
		NodeList children = forumListNode.getChildNodes();
		for (int c = 0; c < children.getLength(); c++) {
			Node child = children.item(c);
			forums.add(extractForum(child));
		}
		
		return forums;
	}
	
	private Forum extractForum(Node forumNode) {
		Forum forum = new Forum();
		
		if (forumNode instanceof Element) {
			Element e = (Element)forumNode;
			forum.setLink(e.getAttribute("id"));
			forum.setTitle(e.getTextContent());
		}
		else {
			forum.setLink("#");
			forum.setTitle("No Title");
		}
		
		return forum;
	}
}
